package com.biz.primus.ms.depot.service;

import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.common.utils.CopyUtils;
import com.biz.primus.common.utils.DateUtil;
import com.biz.primus.common.vo.SpringPageVO;
import com.biz.primus.model.depot.exception.DepotException;
import com.biz.primus.model.depot.vo.DepotDeliverPriceListReqVo;
import com.biz.primus.model.depot.vo.DepotDeliverPriceRespVo;
import com.biz.primus.model.depot.vo.DepotDeliverPriceUpdateVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.depot.dao.po.Depot;
import com.biz.primus.ms.depot.dao.po.DepotDeliverPrice;
import com.biz.primus.ms.depot.dao.redis.DepotDeliverPriceRedisDao;
import com.biz.primus.ms.depot.dao.redis.DepotRedisDao;
import com.biz.primus.ms.depot.dao.repository.DepotDeliverPriceRepository;
import com.biz.primus.ms.depot.dao.repository.DepotRepository;
import com.biz.primus.ms.depot.dao.ro.DepotDeliverPriceRo;
import com.biz.primus.ms.depot.dao.specfication.DepotDeliverPriceSpecification;
import com.biz.primus.ms.depot.trans.DepotDeliverPrice2RespVo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.sql.Timestamp;

/**
 * DepotPriceService
 *
 * @author JKLiues
 * @date 2017年10月23日
 */
@Service
@Slf4j
public class DepotDeliverPriceService extends AbstractBaseService {


    private final DepotDeliverPriceRepository depotDeliverPriceRepository;

    private final DepotDeliverPriceRedisDao depotDeliverPriceRedisDao;
    private final DepotRepository depotRepository;
    private final DepotRedisDao depotRedisDao;


    @Autowired
    public DepotDeliverPriceService(DepotDeliverPriceRepository depotDeliverPriceRepository,
                                    DepotDeliverPriceRedisDao depotDeliverPriceRedisDao,
                                    DepotRepository depotRepository,
                                    DepotRedisDao depotRedisDao) {
        this.depotDeliverPriceRepository = depotDeliverPriceRepository;
        this.depotDeliverPriceRedisDao = depotDeliverPriceRedisDao;
        this.depotRepository = depotRepository;
        this.depotRedisDao = depotRedisDao;
    }

    /**
     * 更新门店起送价
     *
     * @param reqVo 请求VO
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDeliverPrice(DepotDeliverPriceUpdateVo reqVo) {
        String depotCode = reqVo.getDepotCode();
        AssertUtils.notNull(depotCode, DepotException.DEPOT_CODE_IS_NULL);
        Integer price = reqVo.getPrice();
        AssertUtils.notNull(price, DepotException.DEPOT_PRICE_IS_NULL);
        log.info("起送价格更新:{}", reqVo);
        Integer promotionPrice = reqVo.getPromotionPrice();
        String startDate = reqVo.getStartDate();
        String endDate = reqVo.getEndDate();
        DepotDeliverPrice deliverPrice = depotDeliverPriceRepository.findByDepotCode(depotCode);
        if (deliverPrice == null) {
            Depot depot = depotRepository.findByDepotCode(depotCode);
            AssertUtils.notNull(depot, DepotException.DEPOT_NOT_EXIT);
            deliverPrice = new DepotDeliverPrice();
            deliverPrice.setId(idService.getNextId());
            deliverPrice.setDepotCode(depotCode);
            deliverPrice.setName(depot.getName());
        }
        if (promotionPrice != null) {
            Timestamp startDateTime = DateUtil.getTimestamp(startDate, "yyyy-MM-dd");
            AssertUtils.notNull(startDateTime, DepotException.DEPOT_PROMOTION_DATE_IS_NULL);
            Long dayEndTimeMill = DateUtil.getDayEndTime(endDate, "yyyy-MM-dd");
            AssertUtils.notNull(dayEndTimeMill, DepotException.DEPOT_PROMOTION_DATE_IS_NULL);
            Timestamp endDateTime = new Timestamp(dayEndTimeMill);
            AssertUtils.isTrue(endDateTime.before(startDateTime), DepotException.DEPOT_PROMOTION_DATE_IS_WRONG);

            deliverPrice.setPromotionPrice(promotionPrice);
            deliverPrice.setPromotionBegin(startDateTime);
            deliverPrice.setPromotionEnd(endDateTime);
        }
        deliverPrice.setPrice(price);
        depotDeliverPriceRepository.save(deliverPrice);
        DepotDeliverPriceRo depotDeliverPriceRo = new DepotDeliverPriceRo(deliverPrice);

        delayer.executeAfterTransactionCommit(() -> depotDeliverPriceRedisDao.save(depotDeliverPriceRo));

    }

    /**
     * 获取门店起送价配置列表
     *
     * @param reqVo 列表请求VO
     */
    public SpringPageVO<DepotDeliverPriceRespVo> pageResult(DepotDeliverPriceListReqVo reqVo) {
        Page<DepotDeliverPrice> page = depotDeliverPriceRepository.findAll(new DepotDeliverPriceSpecification(reqVo),
                reqVo.toPageRequest());
        return SpringPageVO.<DepotDeliverPriceRespVo>builder()
                .content(Lists.transform(page.getContent(), new DepotDeliverPrice2RespVo()))
                .size((int) page.getTotalElements())
                .size(reqVo.getSize())
                .number(reqVo.getPage())
                .build();
    }

    public DepotDeliverPriceRespVo getDepotDeliverPriceFdb(String depotCode) {
        DepotDeliverPrice depotDeliverPrice = depotDeliverPriceRepository.findByDepotCode(depotCode);
        return new DepotDeliverPrice2RespVo().apply(depotDeliverPrice);
    }

    /**
     * 从redis 获取门店起送价
     *
     * @param depotCode 门店编码
     */
    @Transient
    public DepotDeliverPriceRespVo getDepotDeliverPriceFRdb(String depotCode) {
        AssertUtils.notNull(depotCode, DepotException.DEPOT_NOT_EXIT);
        DepotDeliverPriceRo depotDeliverPrice = depotDeliverPriceRedisDao.findOne(depotCode);
        AssertUtils.notNull(depotDeliverPrice, DepotException.DEPOT_NOT_EXIT);
        DepotDeliverPriceRespVo vo = new DepotDeliverPriceRespVo();
        CopyUtils.copyProperties(depotDeliverPrice, vo);
        return vo;
    }

}